/*
 * jQuery Web Sockets Plugin v0.0.4
 * https://github.com/dchelimsky/jquery-websocket
 * http://code.google.com/p/jquery-websocket/
 *
 * This document is licensed as free software under the terms of the
 * MIT License: http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2010 by shootaroo (Shotaro Tsubouchi).
 */
const TSS_DIALOG = 1;		//对话流
const TSS_PRIVATE = 2;		//会员私有流
const TSS_PUBLIC = 3;		//公共流
const TSS_QUERY = 4;		//查询
const TSS_USER = 5;		//交易员私有流

//用户启动策略请求
const FTD_TID_ReqOptionStg = 0x00002101;
//编辑策略参数请求
const FTD_TID_ReqStgPara = 0x00002102;
//用户登录请求
const FTD_TID_ReqUserLogin = 0x00001001;
//用户登录响应
const FTD_TID_RspUserLogin = 0x00001002;
//用户退出请求
const FTD_TID_ReqUserLogout = 0x00001005;
//用户退出响应
const FTD_TID_RspUserLogout = 0x00001006;
//报单录入请求
const FTD_TID_ReqOrderInsert = 0x00003001;
//报单录入错误时响应
const FTD_TID_RspOrderInsert = 0x00003002;
//报单修改/撤单请求
const FTD_TID_ReqOrderAction = 0x00003003;
//报单修改/撤单错误时响应
const FTD_TID_RspOrderAction = 0x00003004;
//请求查询合约
const FTD_TID_ReqQryInstrument = 0x00002001;
//请求查询合约响应
const FTD_TID_RspQryInstrument = 0x00002002;
//请求查询债券
const FTD_TID_ReqQryBond = 0x00001109;
//请求查询债券响应
const FTD_TID_RspQryBond = 0x0000110A;
//查询债券期货和可交割券关系表
const FTD_TID_ReqQryBondFutureDeliverable = 0x00001105;
//债券期货和可交割券关系表回报
const FTD_TID_RspQryBondFutureDeliverable = 0x00001106;
//请求查询物理账号资金
const FTD_TID_ReqQryAccount = 0x00002005;
//请求查询物理账号资金响应
const FTD_TID_RspQryAccount = 0x00002006;
//请求查询物理账号持仓
const FTD_TID_ReqQryPosition = 0x00002007;
//请求查询物理账号持仓响应
const FTD_TID_RspQryPosition = 0x00002008;
//请求订阅行情
const FTD_TID_ReqSubMarketData = 0x00002009;
//请求退订行情
const FTD_TID_ReqUnSubMarketData = 0x0000200b;
//请求订阅行情BAR
const FTD_TID_ReqSubMarketDataBar = 0x0000200d;
//请求退订行情BAR
const FTD_TID_ReqUnSubMarketDataBar = 0x0000200e;
//请求订阅新本币平台行情
const FTD_TID_ReqSubCFETSMarketData = 0x00001130;
//请求退订新本币平台行情
const FTD_TID_ReqUnsubCFETSMarketData = 0x00001132;
//查询债券成交信息
const FTD_TID_ReqQryBondExecReport = 0x0000110D;
//查询债券成交信息响应
const FTD_TID_RspQryBondExecReport = 0x0000110E;
//请求从行情中心订阅行情
const FTD_TID_ReqSubMDfromMC = 0x00001140;
//请求从行情中心退订行情
const FTD_TID_ReqUnSubMDfromMC = 0x00001142;
//请求订阅策略对应RFQ报价
const FTD_TID_ReqSubRFQByClientID = 0x00001150;
//请求退订策略对应RFQ报价
const FTD_TID_ReqUnSubRFQByClientID = 0x00001152;
//请求增加策略
const FTD_TID_ReqInsertRule = 0x00001010;
//请求增加策略响应
const FTD_TID_RspInsertRule = 0x00001011;
//请求修改策略状态
const FTD_TID_ReqUpdateRuleStatus = 0x00001030;
//请求修改策略状态响应
const FTD_TID_RspUpdateRuleStatus = 0x00001031;
//请求更新策略属性
const FTD_TID_ReqUpdateRuleProp = 0x00001040;
//请求更新策略属性响应
const FTD_TID_RspUpdateRuleProp = 0x00001041;
//策略回报
const FTD_TID_RtnRule = 0x00001012;
//策略运行状态变化回报
const FTD_TID_RtnRuleStatus = 0x00001032;
//策略属性变化回报
const FTD_TID_RtnRuleProp = 0x00001044;
//策略指标回报
const FTD_TID_RtnRuleIndicator = 0x00001045;
//深度行情回报
const FTD_TID_RtnDepthMarketData = 0x00006001;
//行情Bar回报
const FTD_TID_RtnMarketDataBar = 0x00006002;
//报价行情回报
const FTD_TID_RtnQuoteMarket = 0x00001103;
//债券市场成交回报
const FTD_TID_RtnBondExecReport = 0x00001110;
//新本币平台深度行情回报
const FTD_TID_RtnCFETSDepthMarketData = 0x00001133;
//报价接收回报
const FTD_TID_RtnCfetsRFQReceive = 0x00001134;
//CME/CBOT深度行情回报
const FTD_TID_RtnCMEDepthMarketData = 0x00001144;
//报单回报
const FTD_TID_RtnRuleOrder = 0x00001102;
//成交回报
const FTD_TID_RtnRuleTrade = 0x00001111;
//持仓变动回报
const FTD_TID_RtnRulePosition = 0x00001100;
//资金变动回报
const FTD_TID_RtnRuleAccount = 0x00001101;
//Api建立连接回报
const FTD_TID_RtnApiConnected = 0x0000110B;
//Api断开连接回报
const FTD_TID_RtnApiDisconnected = 0x0000110C;
//客户端显示消息回报
const FTD_TID_RtnUserMessage = 0x0000110F;
//用户分账号信息回报
const FTD_TID_RtnCustomerAccountInfo = 0x00001114;
//交易成员基本信息回报
const FTD_TID_RtnCfetsTradeMember = 0x00001135;
//心跳通知
const FTD_TID_NotifyHeartBeat = 0x00004500;
//请求更新合约做市状态
const FTD_TID_ReqUpdMakeMarketStatus = 0x00001115;
//请求更新合约做市状态响应
const FTD_TID_RspUpdMakeMarketStatus = 0x00001116;
//合约做市状态回报
const FTD_TID_RtnMakeMarketStatus = 0x00001117;
//请求更新合约做市参数
const FTD_TID_ReqUpdMakeMarketPara = 0x00001118;
//请求更新合约做市参数响应
const FTD_TID_RspUpdMakeMarketPara = 0x00001119;
//合约做市参数回报
const FTD_TID_RtnMakeMarketPara = 0x0000111A;
//请求查询策略限仓额度
const FTD_TID_ReqQryRulePositionLimit = 0x00001120;
//请求查询策略限仓额度响应
const FTD_TID_RspQryRulePositionLimit = 0x00001121;
//请求更改策略限仓额度
const FTD_TID_ReqRulePositionLimitAction = 0x00001122;
//请求更改策略限仓额度响应
const FTD_TID_RspRulePositionLimitAction = 0x00001123;
//请求订阅价差
const FTD_TID_ReqSubPriceSpread = 0x0000112a;
//请求退订价差
const FTD_TID_ReqUnsubPriceSpread = 0x0000112c;
//合约价差回报
const FTD_TID_RtnInsPriceSpread = 0x0000112b;
//请求手工录入成交数据
const FTD_TID_ReqManualTradeInsert = 0x00001164;
//cta/做市类策略回报
const FTD_TID_RtnCtaMktStg = 0x00002044;


(function ($) {
    $.extend({
        websocket: function (url, s, protocols) {
            var ws, _s = s;
            var settings = {
                message: function () {
                    console.log("message function is undefined");
                },
                options: {}, events: {}, ver: "1.0"
            };
            _reconnect = function (url, protocols) {
                if (protocols) {
                    ws = window['MozWebSocket'] ? new MozWebSocket(url, protocols) : window['WebSocket'] ? new WebSocket(url, protocols) : null;
                } else {
                    ws = window['MozWebSocket'] ? new MozWebSocket(url) : window['WebSocket'] ? new WebSocket(url) : null;
                }
                ws._url = url;
                ws._protocols = protocols;
                $.extend(settings, $.websocketSettings, _s);
                ws.nRequestID = 1;
                if (ws) {
                    $(ws)
                        .bind('open', settings.OnFrontConnected)
                        .bind('close', settings.OnFrontDisconnected)
                        .bind('message', settings.message)
                        .bind('message', function (e) {
                            var m = JSON.stringify(e.originalEvent.data);
                            //eval("m=" + e.originalEvent.data);
                            var h = settings.events[m.Tid];//调用指定的方法
                            if (h) h.call(this, m);
                        });
                    ws._send = ws.send;
                    ws.send = function (type, data) {
                        var m = {Tid: type};//类型
                        m = $.extend(true, m, $.extend(true, {}, settings.options, m));
                        if (data) {
                            delete data["_id"];
                            m['data'] = data;
                        }
                        m['RequestID'] = ws.nRequestID++;
                        return this._send(JSON.stringify(m));
                    };
                    ws.reconnect = function () {
                        setTimeout(function () {
                            _reconnect(ws._url, ws._protocols);
                        }, 1000 * 30);
                        //_reconnect(ws._url, ws._protocols);
                    };
                }
            };
            _reconnect(url, protocols);
            $(window).on("unload", function () {
                ws.close();
                ws = null;
            });
            return ws;
        }


        , trade: function (url, s, protocols) {
            var tradeWS = {nRequestID: 1};

            var settings = {
                OnFrontConnected: function () {
                    console.log("OnFrontConnected");
                },
                OnFrontDisconnected: function () {
                    console.log("OnFrontDisconnected");
                },
                OnRtnApiDisconnected: function (r) {
                },
                OnRtnApiConnected: function (r) {
                },
                OnHeartBeatWarning: function (nTimeLapse) {
                    console.log("OnHeartBeatWarning: " + nTimeLapse);
                },
                OnRspError: function (r) {
                },
                OnRspUserLogin: function (r) {
                },
                OnRspUserLogout: function (r) {
                },
                OnRtnDepthMarketData: function (r) {
                },
                OnRspSubMarketData: function (r) {
                },
                OnRspUnSubMarketData: function (r) {
                },
                OnRtnRule: function (r) {
                },
                OnRtnRuleStatus: function (r) {
                },
                OnRtnRuleProp: function (r) {
                },
                OnRtnCtaMktRule: function (r){
                },
                OnRtnRuleIndicator: function (r) {
                },


                message: function (msg) {
                    try {
                        if (event.data instanceof Blob) {
                            var reader = new FileReader();
                            reader.onloadend = function () {
                                console.log(reader.result);
                            };
                            reader.readAsText(event.data, "gbk");//utf-8
                        } else {
                            eval("r=" + event.data);
                            switch (r.Tid) {
                                case FTD_TID_RtnDepthMarketData: {
                                    tradeWS.OnRtnDepthMarketData(r);
                                    break;
                                }
                                case FTD_TID_RspUserLogin: {
                                    tradeWS.OnRspUserLogin(r);
                                    break;
                                }
                                // case FTD_TID_RspError: {
                                //     tradeWS.OnRspError(r);
                                //     break;
                                // }
                                case FTD_TID_RtnApiDisconnected: {
                                    tradeWS.OnRtnApiDisconnected(r);
                                    break
                                }

                                case FTD_TID_RtnApiConnected: {
                                    tradeWS.OnRtnApiConnected(r);
                                    break
                                }

                                case FTD_TID_RtnRule: {//策略回报
                                    tradeWS.OnRtnRule(r);
                                    break;
                                }
                                case FTD_TID_RtnRuleStatus: {//策略运行状态变化回报
                                    tradeWS.OnRtnRuleStatus(r);
                                    break;
                                }
                                case FTD_TID_RtnRuleProp: {//策略属性变化回报
                                    tradeWS.OnRtnRuleProp(r);
                                    break;
                                }
                                case FTD_TID_RtnCtaMktStg: { //cta,做市类策略回报
                                    tradeWS.OnRtnCtaMktRule(r);
                                    break
                                }
                                case FTD_TID_RtnRuleIndicator: {//策略指标回报
                                    tradeWS.OnRtnRuleIndicator(r);
                                    break;
                                }
                                case FTD_TID_RspUserLogout: {
                                    tradeWS.OnRspUserLogout(r);
                                    break;
                                }
                                case FTD_TID_RspSubMarketData: {
                                    tradeWS.OnRspSubMarketData(r);
                                    break;
                                }
                                case FTD_TID_RspUnSubMarketData: {
                                    tradeWS.OnRspUnSubMarketData(r);
                                    break;
                                }
                                case FTD_TID_IntlRtnDepthMarketData: {
                                    tradeWS.OnRspError(r);
                                    break;
                                }
                                default:
                                    OnHeartBeatWarning(r);
                            }
                            // console.log("log: " + event.data);
                        }
                    } catch (e) {
                        console.log(e.message + " : " + event.data);
                    }
                },
                options: {},
                events: {}
            };
            $.extend(settings, $.websocketSettings, s, tradeWS);
            tradeWS.ws = $.websocket(url, settings, protocols);

            tradeWS.OnFrontConnected = settings.OnFrontConnected;
            tradeWS.OnFrontDisconnected = settings.OnFrontDisconnected;
            tradeWS.OnHeartBeatWarning = settings.OnHeartBeatWarning;
            tradeWS.OnRspError = settings.OnRspError;
            tradeWS.OnRspUserLogin = settings.OnRspUserLogin;
            tradeWS.OnRspUserLogout = settings.OnRspUserLogout;
            tradeWS.OnRtnDepthMarketData = settings.OnRtnDepthMarketData;
            tradeWS.OnRspSubMarketData = settings.OnRspSubMarketData;
            tradeWS.OnRspUnSubMarketData = settings.OnRspUnSubMarketData;
            tradeWS.OnRtnRule = settings.OnRtnRule;
            tradeWS.OnRtnRuleStatus = settings.OnRtnRuleStatus;
            tradeWS.OnRtnRuleProp = settings.OnRtnRuleProp;
            tradeWS.OnRtnCtaMktRule = settings.OnRtnCtaMktRule;
            tradeWS.OnRtnRuleIndicator = settings.OnRtnRuleIndicator;
            tradeWS.OnRtnApiDisconnected = settings.OnRtnApiDisconnected;
            tradeWS.OnRtnApiConnected = settings.OnRtnApiConnected;

            //手工录入发送到后台const ReqManualTradeInsert = 0x00001164;
            tradeWS.OnReqManualTradeInsert = function (bondcode, direction_val, speedliqui_val, tranc, netprice, vol, ruleid, customerid) {
                this.ws.send(FTD_TID_ReqManualTradeInsert, {
                    "bondcode": bondcode,
                    "direction_val": direction_val,
                    "speedliqui_val": speedliqui_val,
                    "tranc": tranc,
                    "netprice": netprice,
                    "vol": vol,
                    "ruleid": ruleid,
                    "customerid": customerid
                })
            };

            //启动或停止策略发送到后台
            tradeWS.ReqOptionStg = function (optype, ruleid, customerid, flag, rulename, typ) {
                console.log("启动", typ)
                this.ws.send(FTD_TID_ReqOptionStg, {
                    "optype": optype,
                    "stgid": ruleid,
                    "customerid": customerid,
                    "flag": flag,
                    "rulename": encodeURI(rulename),
                    "type": typ
                })
            };


            //策略参数发送到websocket
            tradeWS.ReqStgPara = function (customerid, ruleid, key, value, desc) {
                console.log(encodeURI(desc));
                this.ws.send(FTD_TID_ReqStgPara, {
                    "customerid": customerid,
                    "stgid": ruleid,
                    "stgname": encodeURI(key),
                    "stgvalue": encodeURI(value),
                    "stgdesc": encodeURI(desc), //中文乱码，用url编码，python在后台url解码
                })
            }

            tradeWS.ReqUserLogin = function (u, p) {
                this.ws.send(FTD_TID_ReqUserLogin, {
                    'CustomerID': u,
                    'Password': p,
                    'ProductInfo': '',
                    'InterfaceProductInfo': 'websocket'
                });
            };
            tradeWS.SubscribeMarketData = function (ppInstrumentIDs) {
                if (ppInstrumentIDs.length > 0)
                    this.ws.send(FTD_TID_ReqSubMarketData, {'InstrumentID': ppInstrumentIDs, "ExchangeID": "CFFEX"});
                else
                    alert("请选择要订阅行情的合约！");
            };
            tradeWS.UnSubscribeMarketData = function (ppInstrumentIDs) {
                if (ppInstrumentIDs.length > 0)
                    this.ws.send(FTD_TID_ReqUnSubMarketData, {'InstrumentIDs': ppInstrumentIDs});
                else
                    alert("请选择要取消订阅行情的合约！");
            };
            return tradeWS;
        }
    });

})(jQuery);


